﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PPSkin
{
    [DefaultEvent("ValueChanged")]
    public partial class PPRoundProgressBar : UserControl
    {
        public event EventHandler ValueChanged;

        private long value = 0;
        private long minimun = 0;
        private long maximun = 100;
        private long step = 1;
        private int circleWidth = 16;
        private int startAngle = 0;
        private int radius = 10;
        private Color baseColor = Color.LightGray;
        private Color valueColor = Color.DodgerBlue;
        private Color insideColor = Color.LightGray;
        private SHOWType showType = SHOWType.RING;
        private DIRECTION direction = DIRECTION.ClockWise;
        private VALUETYPE valueType = VALUETYPE.PERCENT;

        [Description("进度条值"), Category("自定义")]
        public long Value
        {
            get { return value; }
            set
            {
                if (this.value == value)
                    return;
                if (value > maximun)
                {
                    this.value = maximun;
                }
                else if (value < minimun)
                {
                    this.value = minimun;
                }
                else
                {
                    this.value = value;
                }
                this.Invalidate();
                if (ValueChanged != null)
                {
                    ValueChanged(this, new EventArgs());
                }
                
            }
        }

        [Description("进度条上限"), Category("自定义")]
        public long Maximum
        {
            get { return maximun; }
            set
            {
                if (value < minimun)
                {
                    this.maximun = minimun;
                }
                else
                {
                    this.maximun = value;
                }
            }
        }

        [Description("进度条下限"), Category("自定义")]
        public long Minimum
        {
            get { return minimun; }
            set
            {
                if (value > maximun)
                {
                    this.minimun = maximun;
                }
                else
                {
                    minimun = value;
                }
            }
        }

        [Description("步进增量"), Category("自定义")]
        public long Step
        {
            get { return step; }
            set
            {
                if (value > maximun)
                {
                    step = maximun;
                }
                step = value;
            }
        }

        [Description("圆环宽度"), Category("自定义")]
        public int CircleWidth
        {
            get { return circleWidth; }
            set
            {
                //if(value>base.Width/2)
                //{
                //    circleWidth = base.Width / 2;
                //}
                //else if(value<=0)
                //{
                //    circleWidth = 1;
                //}
                //else
                //{
                circleWidth = value;
                //}
                base.Invalidate();
            }
        }

        [Description("起始角度"), Category("自定义")]
        public int StartAngle
        {
            get { return startAngle; }
            set
            {
                if (value < 0)
                {
                    startAngle = 0;
                }
                else if (value > 360)
                {
                    startAngle = 360;
                }
                else
                {
                    startAngle = value;
                }
            }
        }

        [Description("底色"), Category("自定义")]
        public Color BaseColor
        {
            get { return this.baseColor; }
            set
            {
                this.baseColor = value;
            }
        }

        [Description("有值的颜色"), Category("自定义")]
        public Color ValueColor
        {
            get { return this.valueColor; }
            set
            {
                this.valueColor = value;
            }
        }

        [Description("内部圆的颜色，"), Category("自定义")]
        public Color InsideColor
        {
            get { return this.insideColor; }
            set
            {
                this.insideColor = value;
            }
        }

        [Description("显示类型，扇形或环形"), Category("自定义")]
        public SHOWType ShowType
        {
            get { return showType; }
            set
            {
                showType = value;
            }
        }

        [Description("进度条方向"), Category("自定义")]
        public DIRECTION Direction
        {
            get { return direction; }
            set
            {
                direction = value;
            }
        }

        [Description("文字显示类型，数值和百分比"), Category("自定义")]
        public VALUETYPE ValueType
        {
            get { return valueType; }
            set
            {
                valueType = value;
            }
        }

        public enum SHOWType
        {
            SECTOR,
            RING,
        }

        public enum DIRECTION
        {
            ClockWise,
            AntiClockWise,
        }

        public enum VALUETYPE
        {
            VALUE,
            PERCENT,
        }

        public Enums.DrawMode TextDrawMode { get; set; } = Enums.DrawMode.Anti;

        public PPRoundProgressBar()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.radius = Math.Min(this.Width, this.Height);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            //this.Region = new Region(PaintHelper.CreatePath(new Rectangle(0, 0, this.Width, this.Height), radius));
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            this.radius = Math.Min(this.Width, this.Height);
            if (this.Width != this.Height)
            {
                this.Size = new Size(Math.Min(this.Width, this.Height), Math.Min(this.Width, this.Height));
                //this.Region = new Region(PaintHelper.CreatePath(new Rectangle(0, 0, this.Width, this.Height), radius));
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextDrawMode == Enums.DrawMode.Anti ? System.Drawing.Text.TextRenderingHint.AntiAlias : System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

            Brush brushBase = new SolidBrush(baseColor);
            Brush brushValue = new SolidBrush(valueColor);
            Brush brushText = new SolidBrush(this.ForeColor);
            Pen penBack = new Pen(this.BackColor);

            g.FillEllipse(brushBase, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
            float percent = (float)Math.Round((decimal)this.value / (this.maximun - this.minimun), 2);
            if (direction == DIRECTION.ClockWise)//顺时针
            {
                g.FillPie(brushValue, new Rectangle(0, 0, this.Width - 1, this.Height - 1), (float)(startAngle + 270), (float)(360 * percent));
            }
            else//逆时针
            {
                g.FillPie(brushValue, new Rectangle(0, 0, this.Width - 1, this.Height - 1), (float)(startAngle + 270 - (360 * percent)), (float)(360 * percent));
            }

            if (showType == SHOWType.RING)
            {
                Brush brushInside = new SolidBrush(insideColor);
                g.FillEllipse(brushInside, new Rectangle(circleWidth, circleWidth, this.Width - 1 - 2 * circleWidth, this.Height - 1 - 2 * circleWidth));
                brushInside.Dispose();
            }
            string text = (100 * percent).ToString() + "%";
            if (valueType == VALUETYPE.VALUE)
            {
                text = value.ToString();
            }
            SizeF size = g.MeasureString(text, this.Font);
            g.DrawString(text, this.Font, brushText, new Point(this.Width / 2 - (int)size.Width / 2 - 1, this.Height / 2 - (int)size.Height / 2 + 2));
            GraphicsPath path = PaintHelper.CreatePath(new Rectangle(0, 0, this.Width, this.Height), radius);
            g.DrawPath(penBack, path);

            brushBase.Dispose();
            brushText.Dispose();
            brushValue.Dispose();
            penBack.Dispose();
            path.Dispose();
        }

        public void AddStep()
        {
            if (value + step > maximun)
            {
                Value = maximun;
            }
            else
            {
                Value += step;
            }
        }

        public void ReduceStep()
        {
            if (value - step < minimun)
            {
                Value = minimun;
            }
            else
            {
                Value -= step;
            }
        }
    }
}